package com.qcxk.yuqian.system.component;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 组装MyBatis-Plus条件构造器,前提条件数据库字段名与json对象属性名必须定义规范
 *
 * @param <T>
 * @author KingLee
 * @since 1.0
 */
public class QueryWrapperConverter<T> {

    private static final String LIKE_SQL_KEY = "%";

    private static final String PLACEHOLDER_SQL_KEY = "*";

    private static final String EQ_SQL_KEY = "=";

    private static final String NE_SQL_KEY = "!=";

    private static final String NULL_SQL_KEY = "~null~";

    private static final String NOT_NULL_SQL_KEY = "!=~null~";

    private static final String SPLIT_SQL_KEY = ",";

    private static final String GT_SQL_KEY = ">";

    private static final String GE_SQL_KEY = ">=";

    private static final String LT_SQL_KEY = "<";

    private static final String LE_SQL_KEY = "<=";

    private static final String BETWEEN_SQL_KEY = "between";

    private static final String NOT_BETWEEN_SQL_KEY = "notBetween";

    private static final String AND_SQL_KEY = "and";

    private static final String SWITCH_MATCHES_REGULAR = "[a-z]+[A-Z][a-z]+([A-Z][a-z]+)*";

    private static Pattern pattern = Pattern.compile("[A-Z]");

    /**
     * 判断通配符组装MyBatis-Plus条件构造器
     *
     * @param queryWrapper 对象条件构造器
     * @param queryObject  json对象
     * @param <T>
     */
    public static <T> void converter(QueryWrapper<T> queryWrapper, Object queryObject) {
        // reflect获取实体类的所有属性信息，返回Fields数组
        Field[] fields = queryObject.getClass().getDeclaredFields();
        int fieldLength = fields.length;
        while (fieldLength-- > 0) {
            //属性名
            String fieldName = fields[fieldLength].getName();
            //属性值
            String fieldValue = getFieldValueByFieldName(fieldName, queryObject);
            //表字段名
            String dbFieldName = switchFieldNameToColumnName(fieldName);

            if (StringUtils.isEmpty(fieldValue)) {
                continue;
            }
            //以*%开头，全模糊查询
            if (fieldValue.startsWith(PLACEHOLDER_SQL_KEY + LIKE_SQL_KEY)) {
                queryWrapper.like(dbFieldName, fieldValue.replace(LIKE_SQL_KEY, "").replace(PLACEHOLDER_SQL_KEY, ""));
            }
            //以%结尾
            else if (fieldValue.endsWith(LIKE_SQL_KEY)) {
                queryWrapper.likeRight(dbFieldName, fieldValue.replace(LIKE_SQL_KEY, "").replace(PLACEHOLDER_SQL_KEY, ""));
            }
            //以%开头
            else if (fieldValue.startsWith(LIKE_SQL_KEY)) {
                queryWrapper.likeLeft(dbFieldName, fieldValue.replace(LIKE_SQL_KEY, "").replace(PLACEHOLDER_SQL_KEY, ""));
            }
            //以=开头，完全匹配
            else if (fieldValue.startsWith(EQ_SQL_KEY)) {
                queryWrapper.eq(dbFieldName, fieldValue.replace(EQ_SQL_KEY, ""));
            }
            //!=~null~表示搜索非空值
            else if (fieldValue.startsWith(NOT_NULL_SQL_KEY)) {
                queryWrapper.isNotNull(dbFieldName);
            }
            //以!=开头，完全不匹配
            else if (fieldValue.startsWith(NE_SQL_KEY)) {
                queryWrapper.ne(dbFieldName, fieldValue.replace(NE_SQL_KEY, ""));
            }
            //~null~表示空值
            else if (fieldValue.startsWith(NULL_SQL_KEY)) {
                queryWrapper.isNull(dbFieldName);
            }

            //如果有逗号，则以逗号折开，拼or连接
//            else if (fieldValue.contains(SPLIT_SQL_KEY)) {
//                String[] splitValue = fieldValue.split(SPLIT_SQL_KEY);
//                StringBuffer applySql = new StringBuffer();
//                for (String value : splitValue) {
//                    applySql.append(dbFieldName + " like '" + value + "%' or ");
//                }
//                String finalApplySql = applySql.substring(0,applySql.length()-3);
//                queryWrapper.and(wrapper->wrapper.apply(finalApplySql));
//            }
            //如果有>=，则以>=去做比较
            else if (fieldValue.startsWith(GE_SQL_KEY)) {
                queryWrapper.ge(dbFieldName, fieldValue.replace(GE_SQL_KEY, ""));
            }
            //如果有>，则以>去做比较
            else if (fieldValue.startsWith(GT_SQL_KEY)) {
                queryWrapper.gt(dbFieldName, fieldValue.replace(GT_SQL_KEY, ""));
            }

            //如果有<=，则以<=去做比较
            else if (fieldValue.startsWith(LE_SQL_KEY)) {
                queryWrapper.le(dbFieldName, fieldValue.replace(LE_SQL_KEY, ""));
            }
            //如果有<，则以<去做比较
            else if (fieldValue.startsWith(LT_SQL_KEY)) {
                queryWrapper.lt(dbFieldName, fieldValue.replace(LT_SQL_KEY, ""));
            }

            //如果有between...and...
            else if (fieldValue.toLowerCase().contains(BETWEEN_SQL_KEY)
                    && fieldValue.toLowerCase().contains(AND_SQL_KEY)) {
                String startValue = fieldValue.substring(7, fieldValue.indexOf(AND_SQL_KEY));
                String endValue = fieldValue.substring(fieldValue.indexOf(AND_SQL_KEY) + 3, fieldValue.length());
                queryWrapper.between(dbFieldName, startValue.trim(), endValue.trim());
            }
            //如果有notBetween...and...
//            else if (fieldValue.toLowerCase().contains(NOT_BETWEEN_SQL_KEY.toLowerCase())
//                    && fieldValue.toLowerCase().contains(AND_SQL_KEY)) {
//                String startValue = fieldValue.substring(10, fieldValue.indexOf(AND_SQL_KEY));
//                int lastLetter = fieldValue.indexOf(AND_SQL_KEY) + 3;
//                String endValue = fieldValue.substring(lastLetter, fieldValue.length());
//                queryWrapper.notBetween(dbFieldName, startValue.trim(), endValue.trim());
//            }
            //没有通配符,则模糊查询
            else {
                queryWrapper.like(dbFieldName, fieldValue);
            }
        }
    }

    /**
     * reflect根据类对象属性名获取属性值
     *
     * @param fieldName
     * @param object
     * @return
     */
    public static String getFieldValueByFieldName(String fieldName, Object object) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = object.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(object, new Object[]{});
            return value == null ? null : value.toString();
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            return null;
        }
    }

    /**
     * 根据骆峰属性名转成数据库表对应字段名
     *
     * @param fieldName
     * @return
     * @e.g. companyName->company_name
     */
    public static String switchFieldNameToColumnName(String fieldName) {
        //针对价格做特殊处理
        if (fieldName.equals("priceRange")) {
            return "price";
        }
        if (fieldName.matches(SWITCH_MATCHES_REGULAR)) {
            Matcher matcher = pattern.matcher(fieldName);
            while (matcher.find()) {
                String oldLetter = matcher.group();
                String newLetter = matcher.group().toLowerCase();
                fieldName = fieldName.replaceAll(oldLetter, "_" + newLetter);
            }
        }
        return fieldName;
    }
}
